﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows;

namespace jKinect
{
    public class User32
    {
        [DllImportAttribute("user32.dll", EntryPoint = "SetCursorPos")]
        [return: MarshalAsAttribute(UnmanagedType.Bool)]
        public static extern bool SetCursorPos(int X, int Y);

        [DllImport("user32.dll", SetLastError = true)]
        public static extern uint SendInput(uint nInputs, INPUT[] pInputs, int cbSize);
        [StructLayout(LayoutKind.Sequential)]
        public struct MOUSEINPUT
        {
            public int dx;
            public int dy;
            public uint mouseData;
            public MouseEventFlags dwFlags;
            public uint time;
            public IntPtr dwExtraInfo;
        }

        public enum INPUT_TYPE : int
        {
            TYPE_INPUT_MOUSE = 0,
            TYPE_INPUT_KEYBOARD = 1,
            TYPE_INPUT_HARDWARE = 2
        }
        public const uint KEYEVENTF_EXTENDEDKEY = 0x0001;
        public const uint KEYEVENTF_KEYUP = 0x0002;
        public const uint KEYEVENTF_UNICODE = 0x0004;
        public const uint KEYEVENTF_SCANCODE = 0x0008;
        public const uint XBUTTON1 = 0x0001;
        public const uint XBUTTON2 = 0x0002;

        [Flags]
        public enum MouseEventFlags : uint
        {
            MOVE = 0x00000001,
            LEFTDOWN = 0x00000002,
            LEFTUP = 0x00000004,
            RIGHTDOWN = 0x00000008,
            RIGHTUP = 0x00000010,
            MIDDLEDOWN = 0x00000020,
            MIDDLEUP = 0x00000040,
            XDOWN = 0x00000080,
            XUP = 0x00000100,
            WHEEL = 0x00000800,
            ABSOLUTE = 0x00008000
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct KEYBDINPUT
        {
            /*Virtual Key code.  Must be from 1-254.  If the dwFlags member specifies KEYEVENTF_UNICODE, wVk must be 0.*/
            public ushort wVk;
            /*A hardware scan code for the key. If dwFlags specifies KEYEVENTF_UNICODE, wScan specifies a Unicode character which is to be sent to the foreground application.*/
            public ushort wScan;
            /*Specifies various aspects of a keystroke.  See the KEYEVENTF_ constants for more information.*/
            public uint dwFlags;
            /*The time stamp for the event, in milliseconds. If this parameter is zero, the system will provide its own time stamp.*/
            public uint time;
            /*An additional value associated with the keystroke. Use the GetMessageExtraInfo function to obtain this information.*/
            public IntPtr dwExtraInfo;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct HARDWAREINPUT
        {
            public uint uMsg;
            public ushort wParamL;
            public ushort wParamH;
        }

        [StructLayout(LayoutKind.Explicit)]
        public struct INPUT
        {
            [FieldOffset(0)]
            public INPUT_TYPE type;
            [FieldOffset(sizeof(int))] //[FieldOffset(8)] for x64
            public MOUSEINPUT mi;
            [FieldOffset(sizeof(int))] //[FieldOffset(8)] for x64
            public KEYBDINPUT ki;
            [FieldOffset(sizeof(int))] //[FieldOffset(8)] for x64
            public HARDWAREINPUT hi;
        }

        [DllImport("user32.dll")]
        public static extern IntPtr GetMessageExtraInfo();


        [DllImport("user32.dll")]
        public static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint dwData, int dwExtraInfo);



        //Use the values of this enum for the 'dwData' parameter
        //to specify an X button when using MouseEventFlags.XDOWN or
        //MouseEventFlags.XUP for the dwFlags parameter.
        public enum MouseEventDataXButtons : uint
        {
            XBUTTON1 = 0x00000001,
            XBUTTON2 = 0x00000002
        }



        public static void DoMouse(User32.MouseEventFlags flags, Point coordinates)
        {
            INPUT input = new INPUT();
            input.type = INPUT_TYPE.TYPE_INPUT_MOUSE;
            input.mi = new MOUSEINPUT();
            input.mi.dwExtraInfo = IntPtr.Zero;
            input.mi.dx = (int)(coordinates.X * (65535 / SystemParameters.PrimaryScreenWidth));
            input.mi.dy = (int)(coordinates.Y * (65535 / SystemParameters.PrimaryScreenHeight));
            input.mi.time = 0;
            input.mi.mouseData = 0;  //can be used for WHEEL event see msdn
            input.mi.dwFlags = flags;
            int cbSize = Marshal.SizeOf(typeof(User32.INPUT));
            uint result = User32.SendInput(1, new INPUT[] { input }, cbSize);
            if (result == 0)
                System.Diagnostics.Debug.WriteLine(Marshal.GetLastWin32Error());
        }
    }
}
